package name.marz.to.go.ahg;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import name.marz.to.go.ahg.common.cli.OutDirOption;
import name.marz.to.go.ahg.common.cli.PasswordOption;
import name.marz.to.go.ahg.common.util.HttpUtil;
import name.marz.to.go.ahg.common.util.LogUtil;
import name.marz.to.go.ahg.core.AbstractAutoGetterMain;
import name.marz.to.go.ahg.core.AutoGetterHttpClient;
import name.marz.to.go.ahg.core.exception.UserProcessException;
import name.marz.to.go.ahg.core.executer.AbstractLoginExecuter;
import name.marz.to.go.ahg.core.executer.DocumentGetExecuter;
import name.marz.to.go.ahg.nifty.NiftyLoginExecuter;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.http.client.ClientProtocolException;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;


public class NiftyGetMain extends AbstractAutoGetterMain {
	private static final Logger log = Logger.getLogger(NiftyGetMain.class.getName());
	private static final String DEFAULT_MEISAI_DIRNAME=".";
	
	private AutoGetterHttpClient client = new AutoGetterHttpClient();
	
	private String userId;
	private String password;
	private File outDir;
	
	/**
	 * 
	 */
	public NiftyGetMain() {
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		NiftyGetMain main = new NiftyGetMain();
		main.Main(args);
	}
	
	/* (non-Javadoc)
	 * @see name.marz.to.go.ahg.core.AbstractMain#ready()
	 */
	@Override
	protected void ready() throws Exception {
		super.ready();
	}
	
	@Override
	public Document goTopPage() throws ClientProtocolException, IOException,
			UserProcessException {
		Document doc;
		doc = new DocumentGetExecuter("https://support.nifty.com/billdisp/cgi-bin/billdisp.cgi", client,"TOP").execute();
		LogUtil.log(Level.FINE, client.getCookieStore().getCookies());
		LogUtil.logForms(Level.FINE, doc.getAllElements().forms());
		return doc;
	}

	@Override
	public Document doLogin(Document doc) throws ClientProtocolException, IOException, UserProcessException {
		URI loginUri = HttpUtil.createURISafety("https://sso.nifty.com/pub/login.cgi?service=sptweb05");
		AbstractLoginExecuter le = new NiftyLoginExecuter(loginUri, client, new String[] { userId }, password, doc);
		doc = le.execute();
		LogUtil.logForms(Level.FINE, doc.getAllElements().forms());
		return doc;
	}

	@Override
	public Document goDownloadPage(Document doc)
			throws ClientProtocolException, IOException, UserProcessException {
		return doc;
	}

	@Override
	public File doDownload(Document doc) throws ClientProtocolException,
			IOException, UserProcessException {
		// DocumentをCSVに変換
		log.info("CSV変換中");
		// 年月取り出し
		log.info("年月取り出し開始");
		final String YM_CLASS="seikyu_table01";
		Element elemYM0 = doc.getElementsByClass(YM_CLASS).first();
		if ( elemYM0 == null ) { throw new UserProcessException("divタグ "+YM_CLASS+"が見つかりません"); }
		Element elemYM1 = elemYM0.getElementsByTag("tr").first();
		if ( elemYM1 == null ) { throw new UserProcessException(YM_CLASS+"の中にtrタグが見つかりません"); }
		Element elemYM = elemYM0.getElementsByTag("th").first();
		if ( elemYM == null ) { throw new UserProcessException(YM_CLASS+"の中にthタグが見つかりません"); }
		String strYM = elemYM.text();
		log.info("年月タグ内文字列="+strYM);
		final String YM_PATTERN="(\\d{4})年(\\d{1,2})月度";
		log.info("年月判定正規表現="+YM_PATTERN);
		Pattern p = Pattern.compile(YM_PATTERN);
		Matcher m = p.matcher(strYM);
		if ( !m.find() || m.groupCount() != 2 ) { throw new UserProcessException("文字列"+strYM+"がパターンにマッチしません"); }
		String year = m.group(1);
		String month = String.format("%2s", m.group(2)).replace(' ', '0');
		log.info("年="+year+" 月="+month);
		log.info("年月取り出し終了");
		// ファイルに書き込み
		File file = new File(outDir,year+month+".html");
		String charset = HttpUtil.getCharset(doc);
		log.info("ファイルに書き込み中 "+file.getPath());
		PrintWriter writer = new PrintWriter(file,charset);
		writer.print(doc.html());
		writer.flush();
		writer.close();
		log.info("ファイルに書き込み終了");
		return file;
	}

	@Override
	public void doLogout(Document doc) throws ClientProtocolException,
			IOException, UserProcessException {
		log.info("--何もしない--");
//		URI uri = HttpUtil.createURISafety("https://sso.nifty.com/pub/logout.cgi?service=sptweb05");
//		DocumentGetExecuter executer = new DocumentGetExecuter(uri, client, "logout");
//		Document d = executer.execute();
//		log.finest("logout response="+d.html());
	}

	/* (non-Javadoc)
	 * @see name.marz.to.go.ahg.core.AbstractMain#finish()
	 */
	@Override
	protected void finish() {
		super.finish();
		// 終了処理
		client.getConnectionManager().shutdown();
	}
	
	@SuppressWarnings("static-access")
	@Override
	protected Options getOptions() {
		Options options = new Options();
		Option out = new OutDirOption(false);options.addOption(out);
		options.addOption(OptionBuilder.hasArg(true).withArgName("@nifty id")
				.isRequired(true).withDescription("@niftyユーザー名または@nifty id")
				.create("id"));
		Option password = new PasswordOption(true); options.addOption(password);
		return options;
	}

	@Override
	protected void setParams(CommandLine cmd) {
		userId = cmd.getOptionValue("id");
		this.password = cmd.getOptionValue(PasswordOption.OPT);
		outDir = new File(cmd.getOptionValue(OutDirOption.OPT, DEFAULT_MEISAI_DIRNAME));
	}
}
